#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>

#define MAXLINE 1024
#define TRUE 1
#define FLAG "END\n"      // 结束标志
#define USERNAME "Server" // server名称

// 打印当前时间
void printCurrentTime()
{
    time_t t0 = time(NULL);
    fputs(ctime(&t0), stdout);
}

int main(int argc, char **argv)
{
    int socket_fd, client_fd, signal;
    char recv_message[MAXLINE + 1], send_message[MAXLINE + 1]; // 接受数据buffer和发送数据buffer
    struct sockaddr_in6 servaddr, cliaddr;
    // 打印开始信息
    printf("#########################\n");
    printCurrentTime();
    printf("SocketChat Start!\n");
    printf("This is server: %s \n", USERNAME);
    printf("#########################\n");

    // 创建套接字
    if ((socket_fd = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
    {
        perror("failed to create socket!");
    }

    // 初始化服务器地址
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin6_family = AF_INET6;
    servaddr.sin6_port = htons(20000);
    servaddr.sin6_addr = in6addr_any;

    // 绑定套接字到指定地址
    if (bind(socket_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("failed to bind!");
    }

    if (listen(socket_fd, 5) == -1)
    {
        perror("failed to listen!");
    }

    printf("> Waiting clients ...\r\n");
    socklen_t clilen = sizeof(struct sockaddr);
    client_fd = accept(socket_fd, (struct sockaddr *)&cliaddr, &clilen); // 接受客户端请求
    if (client_fd == -1)
    {
        perror("failed to accept request from client!");
    }

    char user_prefix[20] = {};        // 聊天前缀
    char tmp_send[MAXLINE + 20] = {}; // 发送信息临时buffer
    strcpy(user_prefix, USERNAME);
    strcat(user_prefix, ": "); // 组成前缀
    pid_t pid;
    pid = fork(); // 创建并记录子进程编号
    if (pid < 0)
    {
        perror("failed to fork!");
    }
    if (pid == 0) // 这里用于向client发送聊天数据
    {
        while (fgets(send_message, MAXLINE, stdin) != NULL)
        {
            if (strcmp(send_message, FLAG) == 0)
            {
                signal = send(client_fd, send_message, strlen(send_message), 0); // 发送信息给client
            }
            else
            {
                strcat(tmp_send, user_prefix); // 前缀
                strcat(tmp_send, send_message);
                signal = send(client_fd, tmp_send, strlen(tmp_send), 0); // 发送信息给client
            }
            if (signal < 0)
            {
                perror("failed to send!");
            }
            memset(send_message, 0, strlen(send_message));
            memset(tmp_send, 0, strlen(tmp_send));
        }
        exit(0);
    }
    else
    { // 用于接收client数据
        while (TRUE)
        {
            memset(recv_message, 0, strlen(recv_message)); // 清空接受消息buffer
            signal = read(client_fd, recv_message, sizeof(recv_message)); // 接受client发送信息
            if (signal == -1)
                perror("read error");
            else if (signal == 0)
            {
                printf("client has closed request!\n");
                break; // client退出程序
            }
            if (strcmp(recv_message, FLAG) == 0) // client发送结束信号
            {
                printf("receive close flag from client\n");
                break;
            }
            recv_message[signal] = 0;
            if (fputs(recv_message, stdout) == EOF)
            {
                perror("failed to fput!");
            }
        }
        kill(pid, SIGUSR1); // 结束子进程
    }
    close(client_fd);
    close(socket_fd);
    // 打印结束信息
    printf("#########################\n");
    printf("SocketChat Close\n");
    printf("Close Time:\n");
    printCurrentTime();
    printf("#########################\n");
    exit(0);
}